package com.tanhua.server.service;

import com.alibaba.fastjson.JSON;
import com.tanhua.autoconfig.template.HuanXinTemplate;
import com.tanhua.commons.constants.Constants;
import com.tanhua.commons.exception.TanHuaException;
import com.tanhua.dubbo.api.db.QuestionApi;
import com.tanhua.dubbo.api.db.UserApi;
import com.tanhua.dubbo.api.db.UserInfoApi;
import com.tanhua.dubbo.api.mongo.RecommendUserApi;
import com.tanhua.dubbo.api.mongo.UserLikeApi;
import com.tanhua.dubbo.api.mongo.UserLocationApi;
import com.tanhua.dubbo.api.mongo.VisitorApi;
import com.tanhua.model.db.Question;
import com.tanhua.model.db.User;
import com.tanhua.model.db.UserInfo;
import com.tanhua.model.mongo.RecommendUser;
import com.tanhua.model.mongo.UserLike;
import com.tanhua.model.mongo.UserLocation;
import com.tanhua.model.mongo.Visitors;
import com.tanhua.model.vo.*;
import com.tanhua.server.interceptor.UserHolder;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 通用设置业务处理层
 */
@Service
@Slf4j
public class TanhuaService {

    @DubboReference
    private RecommendUserApi recommendUserApi;

    @DubboReference
    private UserInfoApi userInfoApi;

    @DubboReference
    private QuestionApi questionApi;

    @Autowired
    private HuanXinTemplate huanXinTemplate;

    @DubboReference
    private UserApi userApi;

    private String recommendUserIds = "1,2,3,4,5,6,7,8,9,10";

    @DubboReference
    private UserLikeApi userLikeApi;

    @Autowired
    private RedisTemplate redisTemplate;

    @DubboReference
    private UserLocationApi userLocationApi;

    @DubboReference
    private VisitorApi visitorApi;


    /**
     * 今日佳人
     *
     * @return
     */
    public TodayBestVo todayBest() {
        Long userId = UserHolder.getUserId();//登录用户id
        //1 根据当前用户id查询今日佳人用户（recommend_user）
        RecommendUser recommendUser = recommendUserApi.queryWithMaxScore(userId); //userId:今日佳人用户id  score:当前用户根据佳人缘分值
        //2 如果今日佳人用户为空 设置默认用户（客服）
        if (recommendUser == null) {
            recommendUser = new RecommendUser();
            long bestUserId = userId % 99 + 1;
            recommendUser.setUserId(bestUserId);
            recommendUser.setScore(88d);
        }
        //3 根据今日佳人用户id查询用户信息tb_user_info表
        UserInfo userInfo = userInfoApi.findUserInfo(recommendUser.getUserId());
        //4 TodayBestVo.init(userInfo,recommendUser)
        return TodayBestVo.init(userInfo, recommendUser);
    }

    /**
     * 推荐用户分页列表数据
     *
     * @return
     */
    public PageResult<TodayBestVo> findPageRecommendUser(RecommendUserVo ruv) {
        Long page = ruv.getPage();//当前页码
        Long pageSize = ruv.getPagesize();//每页显示的条数
        Integer age = ruv.getAge();//年龄 < 30
        String gender = ruv.getGender();//性别 gender=1
        Long userId = UserHolder.getUserId();//当前用户id
        //1.根据当前用户id分页查询推荐用户列表数据 100 10页
        PageResult<RecommendUser> recommendUserPageResult = recommendUserApi.findPageRecommendUser(page, pageSize, userId);
        //2.判断没查询到数据 设置默认数据（第一页）
        if (page == 1 && CollectionUtils.isEmpty(recommendUserPageResult.getItems())) {
            recommendUserPageResult.setItems(getDefaultRecommendUserList());
            recommendUserPageResult.setPage(1l);//默认1页
            recommendUserPageResult.setCounts(10l);//总10条
        }
        List<TodayBestVo> bestVoList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(recommendUserPageResult.getItems())) {
            //3.根据推荐用户ids和查询条件查询推荐用户信息
            List<Long> listUserIds = recommendUserPageResult.getItems().stream().map(RecommendUser::getUserId).collect(Collectors.toList());
            UserInfo userInfoCondition = new UserInfo();
            userInfoCondition.setAge(age);
            userInfoCondition.setGender(gender);
            Map<Long, UserInfo> userInfoMap = userInfoApi.findByIds(listUserIds, userInfoCondition);//大概率小于10条
            //4.基于用户信息(tb_user_info) 与 推荐用户表中(recommend_user)数据 构造Vo
            for (RecommendUser recommendUser : recommendUserPageResult.getItems()) {
                Long personUserId = recommendUser.getUserId();//佳人用户id
                UserInfo userInfo = userInfoMap.get(personUserId);
                if (userInfo != null) {
                    bestVoList.add(TodayBestVo.init(userInfo, recommendUser));
                }
            }
        }
        return new PageResult<>(page, pageSize, recommendUserPageResult.getCounts(), bestVoList);
    }


    /**
     * 默认客服
     *
     * @return
     */
    private List<RecommendUser> getDefaultRecommendUserList() {
        List<RecommendUser> list = new ArrayList<>();
        // 随机产生开始的客户id, 从这个客服的id开始，往后取10个
        int startIndex = RandomUtils.nextInt(1, 90);
        RecommendUser recommendUser = null;
        for (long i = startIndex; i < startIndex + 10; i++) {
            recommendUser = new RecommendUser();
            recommendUser.setUserId(i);
            recommendUser.setScore(RandomUtils.nextDouble(70, 88));
            list.add(recommendUser);
        }
        return list;
    }

    /**
     * 佳人信息查询详情
     * @return
     */
    public TodayBestVo personalInfo(Long personUserId) {
        Long userId = UserHolder.getUserId();//当前用户id
        //1根据personUserId查询tb_userInfo获取详情
        UserInfo userInfo = userInfoApi.findUserInfo(personUserId);
        //2根据personUserId和当前用户id查询推荐表获取获取缘分值
        RecommendUser recommendUser = recommendUserApi.findByUserId(userId,personUserId);
        if(recommendUser == null){
            recommendUser = new RecommendUser();
            recommendUser.setUserId(personUserId);
            recommendUser.setScore(Double.valueOf(65+userId%10));
        }
        //2.1 记录访客数据（每个用户每天只会记录一条）
        Visitors visitors = new Visitors();
        visitors.setUserId(personUserId);//被访客的用户id (小红登录用户id)
        visitors.setVisitorUserId(userId);//访客的用户id (峰哥登录用户id)
        visitors.setFrom("首页");//来源，如首页. 圈子等
        visitors.setScore(recommendUser.getScore());//缘分值
        //visitors.setDate();//来访时间
        //visitors.setVisitDate();//来访日期
        visitorApi.addVisitor(visitors);
        //3基于userInfo缘分值构造Vo 返回
        return TodayBestVo.init(userInfo, recommendUser);
    }

    /**
     * 查询陌生人问题
     */
    public String strangerQuestions(Long userId) {
        //1.根据当前用户id查询tb_question表 获取陌生人问题
        Question question = questionApi.findQuestionById(userId);
        if(question != null && StringUtils.isNotEmpty(question.getTxt())){
            return question.getTxt();
        }
        return "约吗?";
    }

    /**
     * 回复陌生人问题
     * 一定要注意：数据名称不能错，数据格式不能错，数据值不能错
     * {
     * 	"userId": 106,
     * 	"huanXinId": "hx106",
     * 	"nickname": "黑马小妹",
     * 	"strangerQuestion": "你喜欢去看蔚蓝的大海还是去爬巍峨的高山？",
     * 	"reply": "我喜欢秋天的落叶，夏天的泉水，冬天的雪地，只要有你一切皆可~"
     * }
     */
    public void addStrangerQuestions(Long personUserId, String reply) {
        //1.根据personUserId获取tb_user表
        User personUser = userApi.findById(personUserId);
        String hxUser = personUser.getHxUser();
        //1.1 构造发送消息内容
        //1.1.1 获取当前用户的信息（发送消息一方）
        User user = UserHolder.getUser();
        //1.1.2 获取当前用户昵称
        UserInfo userInfo = userInfoApi.findUserInfo(user.getId());
        Map<String,Object> map = new HashMap<>();
        map.put("userId",user.getId()); //当前用户id
        map.put("huanXinId",user.getHxUser());//当前用户环信用户名
        map.put("nickname",userInfo.getNickname());//当前用户昵称
        map.put("strangerQuestion",strangerQuestions(personUserId));//佳人陌生人问题
        map.put("reply",reply);//当前登录用户回复内容
        //2.调用环信云发送消息给佳人
        //参数1：发送给谁 hx+用户id 参数2 发送消息内容
        if(!huanXinTemplate.sendMsg(hxUser, JSON.toJSONString(map))){
            throw new TanHuaException(ErrorResult.error());
        }
    }

    /**
     * 探花推荐列表查询
     */
    public List<TodayBestVo> cards() {
        Long currentUserId = UserHolder.getUserId();
        List<RecommendUser> recommendUserList = new ArrayList<>();
        //1 调用服务根据当前登录用户id随机查询10个推荐用户（过滤已经喜欢 不喜欢的用户 作业：过滤好友表表-推荐使用来过滤） recommend_user
        //recommendUserList = recommendUserApi.cards(currentUserId);
        //2 如果推荐的用户数据为空 设置默认10条数据（配置10个客服）
        if(CollectionUtils.isEmpty(recommendUserList)){
            String[] userIds = StringUtils.split(recommendUserIds, ",");
            for (String userId : userIds) {
                RecommendUser recommendUser = new RecommendUser();
                recommendUser.setUserId(Long.valueOf(userId));
                recommendUser.setScore(RandomUtils.nextDouble(70,80));
                recommendUserList.add(recommendUser);
            }
        }
        //3 获取推荐用户ids
        List<Long> recommendUserIds = recommendUserList.stream().map(RecommendUser::getUserId).collect(Collectors.toList());
        //4 根据获取推荐用户ids调用服务获取用户信息tb_userInfo
        Map<Long, UserInfo> userInfoMap = userInfoApi.findByIds(recommendUserIds, null);
        //5 基于recommendUser tbUserInfo构造Vo
        List<TodayBestVo> todayBestVoList = new ArrayList<>();
        for (RecommendUser recommendUser : recommendUserList) {
            todayBestVoList.add(TodayBestVo.init(userInfoMap.get(recommendUser.getUserId()),recommendUser));
        }
        return todayBestVoList;
    }

    /**
     * 探花 - 右滑 flag:true 喜欢 false:不喜欢
     * @param likeUserId 喜欢或不喜欢用户id
     * @return
     */
    public void love(Long likeUserId, boolean flag) {
        log.debug("*************likeUserId**{}********flag***{}*********",likeUserId,flag);
        User user = UserHolder.getUser();
        Long currentUserId = user.getId();//当前用户id
        String hxUser = user.getHxUser();//当前用户环信账号
        //1.调用服务保存喜欢或不喜欢记录user_like  返回值true:互相喜欢 false：没有互相喜欢
        UserLike userLike = new UserLike();
        userLike.setUserId(currentUserId);
        userLike.setLikeUserId(likeUserId);
        userLike.setIsLike(flag);//true:喜欢（右滑） false:不喜欢（左滑）
        boolean isLove = userLikeApi.love(userLike);
        log.debug("*************isLove**{}****************",isLove);
        String likeKey = Constants.USER_LIKE_KEY + UserHolder.getUserId();//key=xxx value=1,2,3,4,5
        String unlikeKey = Constants.USER_NOT_LIKE_KEY + UserHolder.getUserId();
        if(flag){//喜欢
            //2.判断是喜欢 redis喜欢的集合保存 redis不喜欢集合删除
            redisTemplate.opsForSet().add(likeKey,likeUserId);
            redisTemplate.opsForSet().remove(unlikeKey,likeUserId);
        }else {
            //3.判断是不喜欢 redis喜欢的集合删除 redis不喜欢集合保存
            redisTemplate.opsForSet().remove(likeKey,likeUserId);
            redisTemplate.opsForSet().add(unlikeKey,likeUserId);
        }
        //4.如果是互相喜欢 如果是调用环信云保存好友关系
        if(isLove){ //互相喜欢
            //4.1获取喜欢的用户环信账号
            User likeUser = userApi.findById(likeUserId);
            log.debug("*************huanxin*****hxUser*{}*********likeUser**{}********",hxUser,likeUser.getHxUser());
            if(!huanXinTemplate.addContact(hxUser,likeUser.getHxUser())){
                throw new TanHuaException(ErrorResult.error());
            }
        }

    }

    /**
     * 搜附近
     * @param gender 性别
     * @param distance 距离 单位:米 500
     * @return
     */
    public List<NearUserVo> searchNearBy(String gender, Long distance) {
        Long userId = UserHolder.getUserId();
        //1 根据当前用户id和距离搜索userLocation表附近的用户数据
        List<Long> userIds = userLocationApi.searchNearBy(userId,distance);
        List<NearUserVo> nearUserVoList = new ArrayList<>();
        if(!CollectionUtils.isEmpty(userIds)) {
            //2 根据附近用户ids和性别查询用户信息tb_userInfo表
            UserInfo userInfoCondition = new UserInfo();
            userInfoCondition.setGender(gender);//性别条件
            Map<Long, UserInfo> userInfoMap = userInfoApi.findByIds(userIds, userInfoCondition);
            //3 基于用户信息构造Vo返回
            nearUserVoList = userInfoMap.values().stream().map(u -> NearUserVo.init(u)).collect(Collectors.toList());
        }
        return nearUserVoList;
    }
}
